package org.duang.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.duang.common.exceptios.ServiceException;
import org.duang.config.Config;
import org.duang.config.InstanceFactory;
import org.duang.kit.ToolsKit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@WebServlet(name = "pushServlet", urlPatterns = { "/pushservlet" }, asyncSupported = true, loadOnStartup = 1)
public class PushServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;
	private static Logger logger = LoggerFactory.getLogger(PushServlet.class);
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		try {
			if(Config.getPushTimeout() <= -1 && ToolsKit.isEmpty(InstanceFactory.getAsyncContextQueue())) return;
			if (!request.isAsyncSupported()) return;
			request.setCharacterEncoding(Config.getEncoding());
			response.setCharacterEncoding(Config.getEncoding());		
			ServletRequest req = request.startAsync().getRequest();
			if (req.isAsyncStarted()) {
				final AsyncContext asyncContext = req.getAsyncContext();
				asyncContext.setTimeout(Config.getPushTimeout());
				asyncContext.addListener(new AsyncListener() {
					public void onComplete(AsyncEvent event) throws IOException {
						event.getSuppliedResponse().getWriter().close();  
						InstanceFactory.getAsyncContextQueue().remove(event.getAsyncContext());
						logger.warn("asyncContext " + asyncContext.hashCode() + " destroy success!");
					}

					public void onError(AsyncEvent event) throws IOException {
						event.getAsyncContext().complete();
					}

					public void onStartAsync(AsyncEvent event) throws IOException {
					}

					public void onTimeout(AsyncEvent event) throws IOException {
						logger.warn("asyncContext " +asyncContext.hashCode() +" push timeout...");
						event.getAsyncContext().complete();
					}
				});
				
				InstanceFactory.setAsyncContext2Queue(asyncContext);
				logger.warn("add asyncContext to queue success! queue size :" + InstanceFactory.getAsyncContextQueue().size());
				response.setContentType("text/html;charset=" + Config.getEncoding());
				PrintWriter out = response.getWriter();
				out.println("success");
				out.flush();
//				out.close(); 
			}
		} catch (Exception e) {
			e.printStackTrace();			
			throw new ServiceException(e.getMessage());
		}
	}
}
